Event 다루기
✒️ 2025-05-26 14:02 내용 수정
1. Emitting Events
-
서버와 클라이언트 사이에 event를 전송(emit)할 때 사용하는 방법이다.
- 참고 자료 : Socket.IO Emitting events
-
서버 설정
// server
io.on("connection", (socket) => { // listen on connection event
// event를 emit -> 클라이언트에서 hello라는 이벤트 emit 시 hi 사용 가능
socket.emit("hello", "hi");
});
// server
// express 설정
const express = require("express");
const app = express();
// http와 socket.io 설정
const { createServer } = require("http");
const { Server } = require("socket.io");
const server = createServer(app); // express를 사용한 http 서버 생성
const io = new Server(server); // socket 서버 생성
io.on("connection", (socket) => { // listen on connection event
console.log("websocket 연결 완료");
// event를 emit -> 클라이언트에서 hello라는 이벤트 emit 시 hi 사용 가능
socket.emit("hello", "hi");
});
server.listen(3000, () => {
console.log('서버 접속 가능 : http://localhost:3000');
});
app.get("/", (req, res) => {
res.sendFile(__dirname + '/test.html');
})
- 클라이언트 설정
// client
socket.on("hello", (data) => {
console.log(data);
})
// client
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/socket.io@4.7.2/client-dist/socket.io.min.js"></script>
<script>
const socket = io();
socket.on("hello", (data) => {
console.log(data);
})
</script>
</body>
</html>
-
console.log()의 주체가 client이므로 웹 브라우저의 console에 표시된다.
-
위의 방법을 서버와 클라이언트의 코드를 반대로 작성해도 작동한다.
// server
io.on("connection", (socket) => {
socket.on("bye", (data) => {
console.log(data);
});
});
// client
socket.emit("bye", "goodbye");
console.log()의 주체가 server이므로 터미널의 console에 표시된다.
2. Listening to events
- 서버와 클라이언트 사이의 전송되는 이벤트를 다루는 방법이다.
- 서버 사이드에서는 Socket 인스턴스가 Node.js의 EventEmitter 클래스를 상속받고, 클라이언트 사이드에서는 Socket 인스턴스가 component-emitter 라이브러리에서 제공한 event emitter를 사용한다.
- 참고 자료 : Socket.io Listening to events
socket.on("eventName", listenerFn): 특정 이름의 이벤트에 리스너 함수를 추가한다.- 해당 이벤트의 리스너 배열의 맨 마지막에 리스너 함수를 추가한다.
socket.on("eventName", (args) => {
// 특정 이벤트일 때 수행할 내용
});
socket.once("eventName", listenerFn): 특정 이름의 이벤트에 일회용 리스너 함수를 추가한다.
socket.once("eventName", (args) => { // 1번만 발동
// 특정 이벤트일 때 수행할 내용
});
socket.off("eventName", listenerFn): 특정 이름의 이벤트의 리스너 배열에서 특정 리스너 함수를 제거한다.
const tester = (args) = > {
console.log("test listener");
}
// 이벤트에 리스너 추가
socket.on("eventName", tester);
// 추가했던 리스너 제거
socket.off("eventName", tester);
socket.removeAllListener([eventName]): 모든 이벤트 또는 특정 이벤트의 모든 리스너를 제거한다.
// 모든 이벤트의 리스너 제거 시
socket.removeAllListener();
// 특정 이벤트의 리스너 제거 시
socket.removeAllListener("eventName");
3. Broadcasting events
- 연결된 모든 클라이언트에게 이벤트를 전송하는 방법이다.
- 참고 자료 : Socket.io Broadcasting events
- 연결이 끊겨있거나 재연결 상태의 클라이언트는 이벤트를 받을 수 없는 상태이므로, 필요 시엔 이벤트를 다른 곳에 저장했다가 표시하는 것을 처리해야 한다.
- 연결된 모든 클라이언트에게 전송 시
io.emit("hello", "to all clients");
- 메시지 전송자를 제외하고 연결된 모든 클라이언트에게 전송 시
io.on("connection", (socket) => {
socket.broadcast.emit("test", "broadcast test");
})
- 현재 서버에 연결된 모든 클라이언트에게 전송 시
io.local.emit("test", "to all connected clients to this server");
- 특정 room에 있는 클라이언트에게 전송 시
io.to("roomName").emit("hello", "nice to meet you");
- 특정 namespace에만 전송 시
io.of("/specific-namespace").emit("hello", "to specific-users");
4. Room
- Room은 socket들이 참여할 수 있거나 떠날 수 있는 임의의 채널로, event broadcasting을 할 때 사용된다.
- 참고 자료 : Socket.io Rooms
- Room에 참여하려면
join()을 사용한다.
io.on("connection", (socket) => {
socket.join("test room"); // test room에 참여
});
- 특정 이벤트 발생 시 Room에 참여하도록 설정할 수 있다.
io.on("connection", (socket) => {
socket.on("join-request", () => {
socket.join("test room"); // test room에 참여
io.to("test room").emit("eventName"); // test room에 이벤트 전송
});
});
- 연결이 해제될 때 socket은 연결되었던 모든 Room에서 자동으로
leave를 처리한다.- 아래 사진은 웹 페이지 접속 후 웹 브라우저를 닫았을 때 VSC 터미널의 로그다.
// server
io.on("connection", (socket) => {
// test room에 참여를 먼저 수행
socket.on("join-request", () => {
socket.join("test room");
});
// disconnecting 이벤트를 리스닝해서 socket이 있던 Room을 fetch할 수 있다
socket.on("disconnecting", () => {
console.log(socket.rooms); // Set에는 socket ID와 room에 참여했다면 room 이름도 뜬다
});
socket.on("disconnect", () => {
console.log(socket.rooms.size); // 연결 해제 시 자동으로 모든 채널에서 나온다
console.log("모든 채널과 연결이 해제됩니다");
});
});
<!-- client -->
<script src="https://cdn.jsdelivr.net/npm/socket.io@4.7.2/client-dist/socket.io.min.js"></script>
<script>
const socket = io();
socket.emit("join-request"); // 방 참여 event 요청
</script>